#ifndef DHD_CINTERACTION_H
#define DHD_CINTERACTION_H

#include <boost/thread.hpp>
#include <boost/utility.hpp>
#include <boost/function.hpp>
#include <stdint.h>

#include "refcount.h"
#include "buffers.h"
#include "dhd_fs.pb.h"

namespace dhd
{
namespace client
{
   typedef boost::function< void (const ToClient &) >  AsyncCompleteHandler;
   
   class Interaction : public Refcounted, boost::noncopyable
   {
      boost::mutex               imutex;
      boost::condition_variable  icv;
      bool                       notify_on_reply;
      bool                       have_reply;
      bool                       require_reply;
      bool                       do_callback;
      AsyncCompleteHandler       async_callback;
      
    protected:
      void clear();
      
      Interaction();
      
    public:
      uint16_t request_id;
      ToServer request;
      ToClient reply;
      
      PBuffer  pbuffer;
       
      // Used for operations that would prefer to fail quickly rather than wait for a
      // potentially long reconnection period.
      bool     reply_error_on_disconnect;
      
      // Note: The callback function will be executed in the conext of the Server Connection
      //       thread. This will occur immediately prior to notifying the thread (if any)
      //       blocked in 'wait_for_reply()'
      // 
      // Note: If reply_error_on_disconnect is true and the ServerThread is disconnected,
      //       the callback will execute immediately in the context of the calling thread
      //       NOT in the context of the server thread. The result will be -EFAULT.
      void set_async_complete_callback( const AsyncCompleteHandler & cb );
      
      void wait_for_reply();
      void notify_reply_received();
      
      bool reply_required() { return require_reply; }
       
      void set_reply_required( bool b ) { require_reply = b; }
       
      bool check_reply() { return have_reply; }
   };
   
   typedef boost::intrusive_ptr<Interaction> PInteraction;
   
   void delete_interaction_cache();
   
   PInteraction allocate_interaction( bool reply_required = true );
   
} // end namespace dhd::client
} // end namespace dhd

#endif

